#ifndef _H_CARMELA_UTIL_
#define _H_CARMELA_UTIL_

#ifdef __cplusplus
extern "C" {
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <inttypes.h>
#include <sys/signal.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <linux/limits.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <dirent.h>
#include <sys/mman.h>

#include "list.h"
#include "rbtree.h"
#include "LOGC.h"
#include "tcpdaemon.h"
#include "abuf.h"
#include "mempack.h"
#include "netif.h"
#include "hexstr.h"
#include "filex.h"

/*
 * common
 */

#ifndef STRCMP
#define STRCMP(_a_,_C_,_b_) ( strcmp(_a_,_b_) _C_ 0 )
#define STRNCMP(_a_,_C_,_b_,_n_) ( strncmp(_a_,_b_,_n_) _C_ 0 )
#endif

#ifndef MEMCMP
#define MEMCMP(_a_,_C_,_b_,_n_) ( memcmp(_a_,_b_,_n_) _C_ 0 )
#endif

/*
 * mempack log macro
 */

#define IF_LEN_NE_THEN_LOG(_expect_len_,_return_,_log_content_prefix_,_if_ok_log_postfix_,...) \
	if( ( nret = ( len != (_expect_len_) ) ) ) \
	{ \
		ERRORLOG( _log_content_prefix_ " failed[%d]" , len ) \
		_return_; \
	} \
	else \
	{ \
		DEBUGLOG( _log_content_prefix_ " ok , " _if_ok_log_postfix_ , __VA_ARGS__ ) \
	} \

#define MEMPACK_COMM_VERSION(_return_,_comm_version_,_comm_data_) \
	if( _comm_data_ ) { \
		ssize_t len = MemPack_uint8_to_1byte( _comm_version_ , _comm_data_ ) ; \
		IF_LEN_NE_THEN_LOG( 1 , _return_ ,"MemPack_uint8_to_1byte comm_version" , "comm_version[%c][0x%02X]" , _comm_version_ , _comm_version_ ) \
	} \

#define MEMPACK_PROCESS_CODE(_return_,_process_code_,_comm_data_) \
	if( _comm_data_ ) { \
		ssize_t len = MemPack_uint32_to_4byte_nobyteorder( _process_code_.u32 , _comm_data_ ) ; \
		IF_LEN_NE_THEN_LOG( 4 , _return_ ,"MemPack_uint32_to_4byte_nobyteorder process_code" , "process_code[%.4s][0x%02X 0x%02X 0x%02X 0x%02X]" , _process_code_.str , _process_code_.str[0],_process_code_.str[1],_process_code_.str[2],_process_code_.str[3] ) \
	} \

#define MEMPACK_STORE_NAME_LEN(_return_,_store_len_,_comm_data_) \
	if( _comm_data_ ) { \
		ssize_t len = MemPack_uint8_to_1byte( _store_len_ , _comm_data_ ) ; \
		IF_LEN_NE_THEN_LOG( 1 , _return_ ,"MemPack_uint8_to_1byte store_len" , "store_len[%"PRIu8"]" , _store_len_ ) \
	} \

#define MEMPACK_STORE_NAME(_return_,_store_,_store_len_,_comm_data_) \
	if( _comm_data_ ) { \
		ssize_t len = MemPack_charpt_to_nbyte( _store_ , _store_len_ , _comm_data_ ) ; \
		IF_LEN_NE_THEN_LOG( _store_len_ , _return_ ,"MemPack_charpt_to_nbyte store" , "store[%s]" , _store_ ) \
	} \

#define MEMPACK_TOPIC_NAME_LEN(_return_,_topic_len_,_comm_data_) \
	if( _comm_data_ ) { \
		ssize_t len = MemPack_uint8_to_1byte( _topic_len_ , _comm_data_ ) ; \
		IF_LEN_NE_THEN_LOG( 1 , _return_ ,"MemPack_uint8_to_1byte topic_len" , "topic_len[%"PRIu8"]" , _topic_len_ ) \
	} \

#define MEMPACK_TOPIC_NAME(_return_,_topic_,_topic_len_,_comm_data_) \
	if( _comm_data_ ) { \
		ssize_t len = MemPack_charpt_to_nbyte( _topic_ , _topic_len_ , _comm_data_ ) ; \
		IF_LEN_NE_THEN_LOG( _topic_len_ , _return_ ,"MemPack_charpt_to_nbyte topic" , "topic[%s]" , _topic_ ) \
	} \

#define MEMPACK_SUBSCRIBE_GROUP_NAME_LEN(_return_,_subsribe_group_len_,_comm_data_) \
	if( _comm_data_ ) { \
		ssize_t len = MemPack_uint8_to_1byte( _subsribe_group_len_ , _comm_data_ ) ; \
		IF_LEN_NE_THEN_LOG( 1 , _return_ ,"MemPack_uint8_to_1byte subscribe_group_len" , "subscribe_group_len[%"PRIu8"]" , _subsribe_group_len_ ) \
	} \

#define MEMPACK_SUBSCRIBE_GROUP_NAME(_return_,_subsribe_group_,_subsribe_group_len_,_comm_data_) \
	if( _comm_data_ ) { \
		ssize_t len = MemPack_charpt_to_nbyte( _subsribe_group_ , _subsribe_group_len_ , _comm_data_ ) ; \
		IF_LEN_NE_THEN_LOG( _subsribe_group_len_ , _return_ ,"MemPack_charpt_to_nbyte subscribe_group" , "subscribe_group[%s]" , _subsribe_group_ ) \
	} \

#define MEMPACK_TAGS_LEN(_return_,_tags_len_,_comm_data_) \
	if( _comm_data_ ) { \
		ssize_t len = MemPack_uint16_to_2byte( _tags_len_ , _comm_data_ ) ; \
		IF_LEN_NE_THEN_LOG( 2 , _return_ ,"MemPack_uint16_to_2byte tags_len" , "tags_len[%"PRIu16"]" , _tags_len_ ) \
	} \

#define MEMPACK_TAGS(_return_,_tags_,_tags_len_,_comm_data_) \
	if( _comm_data_ ) { \
		ssize_t len = MemPack_charpt_to_nbyte( _tags_ , _tags_len_ , _comm_data_ ) ; \
		IF_LEN_NE_THEN_LOG( _tags_len_ , _return_ ,"MemPack_charpt_to_nbyte tags" , "tags[%s]" , _tags_ ) \
	} \

#define MEMPACK_MSG_DATA_LEN(_return_,_msg_data_len_,_comm_data_) \
	if( _comm_data_ ) { \
		ssize_t len = MemPack_uint32_to_4byte( _msg_data_len_ , _comm_data_ ) ; \
		IF_LEN_NE_THEN_LOG( 4 , _return_ ,"MemPack_uint32_to_4byte msg_data_len" , "msg_data_len[%"PRIu32"]" , _msg_data_len_ ) \
	} \

#define MEMPACK_MSG_DATA(_return_,_msg_data_,_msg_data_len_,_comm_data_) \
	if( _comm_data_ ) { \
		ssize_t len = MemPack_charpt_to_nbyte( _msg_data_ , _msg_data_len_ , _comm_data_ ) ; \
		IF_LEN_NE_THEN_LOG( _msg_data_len_ , _return_ ,"MemPack_charpt_to_nbyte msg_data" , "msg_data[%s]" , _msg_data_ ) \
	} \

#define MEMPACK_DELAY_SECONDS(_return_,_delay_seconds_,_comm_data_) \
	if( _comm_data_ ) { \
		ssize_t len = MemPack_uint32_to_4byte( _delay_seconds_ , _comm_data_ ) ; \
		IF_LEN_NE_THEN_LOG( 4 , _return_ ,"MemPack_uint32_to_4byte delay_seconds" , "delay_seconds[%"PRIu32"]" , _delay_seconds_ ) \
	} \

#define MEMPACK_RESULT(_return_,_result_,_comm_data_) \
	if( _comm_data_ ) { \
		ssize_t len = MemPack_uint16_to_2byte( _result_ , _comm_data_ ) ; \
		IF_LEN_NE_THEN_LOG( 2 , _return_ ,"MemPack_uint16_to_2byte result" , "result[%"PRIu16"]" , _result_ ) \
	} \

#define MEMPACK_MSG_OFFSET(_return_,_msg_offset_,_comm_data_) \
	if( _comm_data_ ) { \
		ssize_t len = MemPack_uint64_to_8byte( _msg_offset_ , _comm_data_ ) ; \
		IF_LEN_NE_THEN_LOG( 8 , _return_ ,"MemPack_uint64_to_8byte msg_offset" , "msg_offset[%"PRIu32"]" , _msg_offset_ ) \
	} \

#define MEMPACK_TOPIC_OFFSET(_return_,_topic_offset_,_comm_data_) \
	if( _comm_data_ ) { \
		ssize_t len = MemPack_uint64_to_8byte( _topic_offset_ , _comm_data_ ) ; \
		IF_LEN_NE_THEN_LOG( 8 , _return_ ,"MemPack_uint64_to_8byte topic_offset" , "topic_offset[%"PRIu32"]" , _topic_offset_ ) \
	} \

#define MEMPACK_DELAY_MSG_OFFSET(_return_,_delay_msg_offset_,_comm_data_) \
	if( _comm_data_ ) { \
		ssize_t len = MemPack_uint64_to_8byte( _delay_msg_offset_ , _comm_data_ ) ; \
		IF_LEN_NE_THEN_LOG( 8 , _return_ ,"MemPack_uint64_to_8byte delay_msg_offset" , "delay_msg_offset[%"PRIu32"]" , _delay_msg_offset_ ) \
	} \

#define MEMUNPACK_COMM_VERSION(_return_,_comm_data_,_comm_version_) \
	if( _comm_data_ ) { \
		ssize_t len = MemUnpack_1byte_to_uint8( _comm_data_ , & _comm_version_ ) ; \
		IF_LEN_NE_THEN_LOG( 1 , _return_ ,"MemUnpack_1byte_to_uint8 comm_version" , "comm_version[%c][0x%02X]" , _comm_version_ , _comm_version_ ) \
	} \

#define MEMUNPACK_PROCESS_CODE(_return_,_comm_data_,_process_code_) \
	if( _comm_data_ ) { \
		ssize_t len = MemUnpack_4byte_to_uint32_nobyteorder( _comm_data_ , & (_process_code_.u32) ) ; \
		IF_LEN_NE_THEN_LOG( 4 , _return_ ,"MemUnpack_4byte_to_uint32_nobyteorder process_code" , "process[%.4s][0x%02X 0x%02X 0x%02X 0x%02X]" , _process_code_.str , _process_code_.str[0],_process_code_.str[1],_process_code_.str[2],_process_code_.str[3] ) \
	} \

#define MEMUNPACK_STORE_NAME_LEN(_return_,_comm_data_,_store_len_) \
	if( _comm_data_ ) { \
		ssize_t len = MemUnpack_1byte_to_uint8( _comm_data_ , & _store_len_ ) ; \
		IF_LEN_NE_THEN_LOG( 1 , _return_ ,"MemUnpack_1byte_to_uint8 store_len" , "store_len[%zu]" , _store_len_ ) \
	} \

#define MEMUNPACK_STORE_NAME(_return_,_comm_data_,_store_len_,_store_) \
	if( _comm_data_ ) { \
		ssize_t len = MemUnpack_nbyte_to_charpt( _comm_data_ , _store_len_ , & _store_ ) ; \
		IF_LEN_NE_THEN_LOG( _store_len_ , _return_ ,"MemUnpack_nbyte_to_charpt store" , "store[%zu][%.*s]" , _store_len_ , _store_len_,_store_ ) \
	} \

#define MEMUNPACK_TOPIC_NAME_LEN(_return_,_comm_data_,_topic_len_) \
	if( _comm_data_ ) { \
		ssize_t len = MemUnpack_1byte_to_uint8( _comm_data_ , & _topic_len_ ) ; \
		IF_LEN_NE_THEN_LOG( 1 , _return_ ,"MemUnpack_1byte_to_uint8 topic_len" , "topic_len[%zu]" , _topic_len_ ) \
	} \

#define MEMUNPACK_TOPIC_NAME(_return_,_comm_data_,_topic_len_,_topic_) \
	if( _comm_data_ ) { \
		ssize_t len = MemUnpack_nbyte_to_charpt( _comm_data_ , _topic_len_ , & _topic_ ) ; \
		IF_LEN_NE_THEN_LOG( _topic_len_ , _return_ ,"MemUnpack_nbyte_to_charpt topic" , "topic[%zu][%.*s]" , _topic_len_ , _topic_len_,_topic_ ) \
	} \

#define MEMUNPACK_SUBSCRIBE_GROUP_NAME_LEN(_return_,_comm_data_,_subscribe_group_len_) \
	if( _comm_data_ ) { \
		ssize_t len = MemUnpack_1byte_to_uint8( _comm_data_ , & _subscribe_group_len_ ) ; \
		IF_LEN_NE_THEN_LOG( 1 , _return_ ,"MemUnpack_1byte_to_uint8 subscribe_group_len" , "subscribe_group_len[%zu]" , _subscribe_group_len_ ) \
	} \

#define MEMUNPACK_SUBSCRIBE_GROUP_NAME(_return_,_comm_data_,_subscribe_group_len_,_subscribe_group_) \
	if( _comm_data_ ) { \
		ssize_t len = MemUnpack_nbyte_to_charpt( _comm_data_ , _subscribe_group_len_ , & _subscribe_group_ ) ; \
		IF_LEN_NE_THEN_LOG( _subscribe_group_len_ , _return_ ,"MemUnpack_nbyte_to_charpt subscribe_group" , "subscribe_group[%zu][%.*s]" , _subscribe_group_len_ , _subscribe_group_len_,_subscribe_group_ ) \
	} \

#define MEMUNPACK_TAGS_LEN(_return_,_comm_data_,_tags_len_) \
	if( _comm_data_ ) { \
		ssize_t len = MemUnpack_2byte_to_uint16( _comm_data_ , & _tags_len_ ) ; \
		IF_LEN_NE_THEN_LOG( 2 , _return_ ,"MemUnpack_2byte_to_uint16 tags_len" , "tags_len[%zu]" , _tags_len_ ) \
	} \

#define MEMUNPACK_TAGS(_return_,_comm_data_,_tags_len_,_tags_) \
	if( _comm_data_ ) { \
		ssize_t len = MemUnpack_nbyte_to_charpt( _comm_data_ , _tags_len_ , & _tags_ ) ; \
		IF_LEN_NE_THEN_LOG( _tags_len_ , _return_ ,"MemUnpack_nbyte_to_charpt tags" , "tags[%zu][%.*s]" , _tags_len_ , _tags_len_,_tags_ ) \
	} \

#define MEMUNPACK_MSG_DATA_LEN(_return_,_comm_data_,_msg_data_len_) \
	if( _comm_data_ ) { \
		ssize_t len = MemUnpack_4byte_to_uint32( _comm_data_ , & _msg_data_len_ ) ; \
		IF_LEN_NE_THEN_LOG( 4 , _return_ ,"MemUnpack_4byte_to_uint32 msg_data_len" , "msg_data_len[%zu]" , _msg_data_len_ ) \
	} \

#define MEMUNPACK_MSG_DATA(_return_,_comm_data_,_msg_data_len_,_msg_data_) \
	if( _comm_data_ ) { \
		ssize_t len = MemUnpack_nbyte_to_charpt( _comm_data_ , _msg_data_len_ , & _msg_data_ ) ; \
		IF_LEN_NE_THEN_LOG( _msg_data_len_ , _return_ ,"MemUnpack_nbyte_to_charpt msg_data" , "msg_data[%zu][%.*s]" , _msg_data_len_ , _msg_data_len_,_msg_data_ ) \
	} \

#define MEMUNPACK_DELAY_SECONDS(_return_,_comm_data_,_delay_seconds_) \
	if( _comm_data_ ) { \
		ssize_t len = MemUnpack_4byte_to_uint32( _comm_data_ , & _delay_seconds_ ) ; \
		IF_LEN_NE_THEN_LOG( 4 , _return_ ,"MemUnpack_4byte_to_uint32 delay_seconds_" , "delay_seconds_[%"PRIu32"]" , _delay_seconds_ ) \
	} \

#define MEMUNPACK_RESULT(_return_,_comm_data_,_result_) \
	if( _comm_data_ ) { \
		ssize_t len = MemUnpack_2byte_to_uint16( _comm_data_ , & _result_ ) ; \
		IF_LEN_NE_THEN_LOG( 2 , _return_ , "MemUnpack_2byte_to_uint16 result" , "result[%"PRIu16"]" , _result_ ) \
	} \

#define MEMUNPACK_MSG_OFFSET(_return_,_comm_data_,_msg_offset_) \
	if( _comm_data_ ) { \
		ssize_t len = MemUnpack_8byte_to_uint64( _comm_data_ , & _msg_offset_ ) ; \
		IF_LEN_NE_THEN_LOG( 8 , _return_ ,"MemUnpack_8byte_to_uint64 msg_offset" , "msg_offset[%zu]" , _msg_offset_ ) \
	} \

#define MEMUNPACK_TOPIC_OFFSET(_return_,_comm_data_,_topic_offset_) \
	if( _comm_data_ ) { \
		ssize_t len = MemUnpack_8byte_to_uint64( _comm_data_ , & _topic_offset_ ) ; \
		IF_LEN_NE_THEN_LOG( 8 , _return_ ,"MemUnpack_8byte_to_uint64 topic_offset" , "topic_offset[%zu]" , _topic_offset_ ) \
	} \

#define MEMUNPACK_DELAY_MSG_OFFSET(_return_,_comm_data_,_delay_msg_offset_) \
	if( _comm_data_ ) { \
		ssize_t len = MemUnpack_8byte_to_uint64( _comm_data_ , & _delay_msg_offset_ ) ; \
		IF_LEN_NE_THEN_LOG( 8 , _return_ ,"MemUnpack_8byte_to_uint64 delay_msg_offset" , "delay_msg_offset[%zu]" , _delay_msg_offset_ ) \
	} \

/*
 * mempack log macro
 */

extern char		*__CARMELA_VER ;

#ifdef __cplusplus
}
#endif

#endif

